package megrez.common.spring.security;

import java.util.Optional;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.jwt.Jwt;

import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

/**
 * 安全工具
 *  
 * @author Lucky Yang
 * @since 8.4.1
 */
@UtilityClass
@Slf4j
public class SecurityUtils {
    public static final String PREFERRED_USERNAME = "preferred_username";


    public String getCurrentUser() {
        return getCurrentUserOptional().orElse(null);
    }

    public Optional<String> getCurrentUserOptional() {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        final Authentication authentication = securityContext.getAuthentication();

        if (authentication == null) {
            return Optional.ofNullable(null);
        }

        Object principal = authentication.getPrincipal();
        if (log.isDebugEnabled()) {
            log.debug("The current user is {}", principal);
        }

        
        if (Jwt.class.isAssignableFrom(principal.getClass())) {
            // jwt令牌
            final String username = ((Jwt)principal).getClaimAsString(PREFERRED_USERNAME);
            return Optional.ofNullable(username);
        }

        if (User.class.isAssignableFrom(principal.getClass())) {
            return Optional.of(((User) principal).getUsername());
        }

        if (DefaultOidcUser.class.isAssignableFrom(principal.getClass())) {
            return Optional.ofNullable(((DefaultOidcUser) principal).getAttribute(PREFERRED_USERNAME));
        }

        if (String.class.isAssignableFrom(principal.getClass())) {
            return Optional.ofNullable((String) principal);
        }

        return Optional.ofNullable(null);
    }    
}
